--<<<
format debug "--  Compiling Instrument Class . . .\n" undefined undefined
class InstDap(DigitalAudioPlayer)
inst vars
	owner
end

method syncYourself self {class InstDap} state ->
(
	syncYourself self.owner state
)

class Instrument(TwoDShape)
inst vars
	bitmaps
	dap
	activated
	mouseUp
	mouseCross
	loopCB
	name
end

method init self {class Instrument} #rest args #key castNum: lingo: ->
(
	local bitmaps := new HashTable
	add bitmaps @off castList[castNum].boundary
	local onCast := castFromName(findSXKey(lingo,"hilite"))
	if onCast = empty then (
		report generalError "hilite keyword invalid or missing."
	) else (
		add bitmaps @on onCast.boundary
	)
	local acName := findSXKey(lingo,"sound")
	self.name := acName
	format debug "instrument sound: %*\n" acName @unadorned
	local audioCast := castFromName(acName)
	if audioCast = empty then (
		report generalError "sound keyword invalid or missing."
	)
	apply nextMethod self boundary:(bitmaps[@off]) args
	local myDap := new InstDap  mediaStream:audioCast bufSize:100
	myDap.owner := self
	self.dap := myDap
	self.bitmaps := bitmaps
	self.activated := false
	return self
)

method afterInit self {class Instrument} #rest args ->
(
	local myPlayer := self.dap
	gotoBegin myPlayer
	playprepare myPlayer 1
	return self
)

method mouseUpSelect self {class Instrument} theInterest theEvent ->
(
	local activated := (self.activated = false)
	local myPlayer := self.dap
	if myPlayer.masterClock = undefined do
		myPlayer.masterClock := self.presentedBy.sceneMasterClock
	if activated then (
		self.boundary := self.bitmaps[@on]
		if self.loopCB = undefined do (
			self.loopCB := addTimeCallback myPlayer gotoBegin myPlayer #() (myPlayer.duration) false
			format debug "Slave callback for %*\n" self.name @unadorned
		)
		playPrepare myPlayer 1
		play myPlayer
		removeEventInterest self.mouseCross
	) else (
		self.boundary := self.bitmaps[@off]
		stop myPlayer
		gotoBegin myPlayer
		addEventInterest self.mouseCross
	)
	self.activated := activated
)

method mouseRollover self {class Instrument} theInterest theEvent ->
(
--	local activated := self.activated
--	if not activated do ( 
	case theEvent.crossingType of
		@enter: self.boundary := self.bitmaps[@on]
		@leave: self.boundary := self.bitmaps[@off]
	end
--	)
)

method hook self {class Instrument} ->
(
	local mouseDev := new MouseDevice
	local muEvent := self.mouseUp
	if not (isAKindOf muEvent MouseUpEvent) do (
		muEvent := new MouseUpEvent
		muEvent.eventReceiver := mouseUpSelect
		muEvent.authorData := self
		muEvent.device := mouseDev
		muEvent.presenter := self
		self.mouseUp := muEvent
	)
	addEventInterest muEvent
	local mcEvent := self.mouseCross
	if not (isAKindOf mcEvent MouseCrossingEvent) do (
		mcEvent := new MouseCrossingEvent
		mcEvent.eventReceiver := mouseRollover
		mcEvent.authorData := self
		mcEvent.device := mouseDev
		mcEvent.presenter := self
		self.mouseCross := mcEvent
	)
	addEventInterest mcEvent
)

method unhook self {class Instrument} ->
(
	removeEventInterest self.mouseUp
	removeEventInterest self.mouseCross
	local cb := self.loopCB
	if cb <> undefined do (
		cancel cb
		self.loopCB := undefined
	)
	self.boundary := self.bitmaps[@off]
	stop self.dap
	gotoBegin self.dap
)

method slaveTo self {class Instrument} newMaster ->
(
	self.dap.masterClock := newMaster
	format debug "Slaving %1 to %2\n" #(self.name, newMaster) #(@unadorned,@unadorned)
)

method syncYourself self {class Instrument} state ->
(
	local cb := self.loopCB
	local dap := self.dap
	case state of
		@sync:	(
					if cb <> undefined do (
						cancel cb
						self.loopCB := undefined
					)
					dap.time := 0
				)
		@nosync:(
					if cb = undefined do (
						self.loopCB := addTimeCallback dap gotoBegin dap #() (dap.duration) false
						format debug "Slave callback for %*\n" self.name @unadorned
						if dap.duration < dap.time do gotoBegin dap
					)
				)
		otherwise:	(
					format debug "%1 state: %2\n" #(self.name, state)
					report GeneralError "invalid state"
				)
	end
	format debug "state  of %1 to %2\n" #(self.name, state) #(@unadorned,@unadorned)
)

#(Instrument, #("activated","bitmaps"), #("hook","unhook"))
